package cn.dduan.fool.collection.list;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * ArrayList
 * <p>
 * 优点: 底层数据结构是数组，查询快，增删慢
 * <p>
 * 缺点: 线程不安全，效率高
 * <p>
 * 并发修改 ArrayList 抛出 ConcurrentModificationException 异常
 *
 * 实现ArrayList线程安全的方法
 * 1. 使用 Vector 代替 ArrayList。（不推荐，Vector是一个历史遗留类）
 * 2. 使用 Collections.synchronizedList 包装 ArrayList，然后操作包装后的 list。
 * 3. 使用 CopyOnWriteArrayList 代替 ArrayList。
 * 4. 在使用 ArrayList 时，应用程序通过同步机制去控制 ArrayList 的读写。
 *
 * @author dduan
 * @version 1.0
 * @date 2023/3/27
 */
public class MyArrayList {
    public static void main(String[] args) {
        // MyArrayList.threadNotSafe();
        // MyArrayList.vectorList();
        // MyArrayList.synchronizedList();
        // MyArrayList.copyOnWriteArrayList();
        MyArrayList.syncList();
    }

    /**
     * 使用 synchronized 关键字实现线程安全
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/10
     */
    private static void syncList() {
        ArrayList<Object> list = new ArrayList<>();
        Object lock = new Object();

        Thread t1 = new Thread(() -> {
            System.out.println("线程：" + Thread.currentThread().getName());
            for (int i = 0; i < 50; i++) {
                synchronized (lock) {
                    list.add(i);
                }
            }
        });
        t1.start();

        Thread t2 = new Thread(() -> {
            System.out.println("线程：" + Thread.currentThread().getName());
            for (int i = 0; i < 50; i++) {
                synchronized (lock) {
                    list.add(i);
                }
            }
        });
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        System.out.println(list.toString());
    }

    /**
     * CopyOnWriteArrayList 实现线程安全
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/10
     */
    private static void copyOnWriteArrayList() {
        List<Integer> list = new CopyOnWriteArrayList<>();

        Thread t1 = new Thread(() -> {
            System.out.println("线程：" + Thread.currentThread().getName());
            for (int i = 0; i < 50; i++) {
                list.add(i);
            }
        });
        t1.start();

        Thread t2 = new Thread(() -> {
            System.out.println("线程：" + Thread.currentThread().getName());
            for (int i = 0; i < 50; i++) {
                list.add(i);
            }
        });
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        System.out.println(list.toString());
    }

    /**
     * Collections.synchronizedList ArrayList 线程安全
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/10
     */
    private static void synchronizedList() {
        List<Integer> noSyncList = new ArrayList<>(100);
        List<Integer> syncList = Collections.synchronizedList(noSyncList);

        Thread t1 = new Thread(() -> {
            System.out.println("线程：" + Thread.currentThread().getName());
            for (int i = 0; i < 50; i++) {
                syncList.add(i);
            }
        });
        t1.start();

        Thread t2 = new Thread(() -> {
            System.out.println("线程：" + Thread.currentThread().getName());
            for (int i = 0; i < 50; i++) {
                syncList.add(i);
            }
        });
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        System.out.println(syncList.toString());
    }

    /**
     * Vector 实现 ArrayList 线程安全
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/10
     */
    private static void vectorList() {
        List<Integer> list = new Vector<>(100);

        Thread t1 = new Thread(() -> {
            System.out.println("线程：" + Thread.currentThread().getName());
            for (int i = 0; i < 50; i++) {
                list.add(i);
            }
        });
        t1.start();

        Thread t2 = new Thread(() -> {
            System.out.println("线程：" + Thread.currentThread().getName());
            for (int i = 0; i < 50; i++) {
                list.add(i);
            }
        });
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        System.out.println(list.toString());
    }

    /**
     * ArrayList 线程不安全抛出异常
     *
     * @author dduan
     * @version 1.0
     * @date 2025/3/7
     */
    private static void threadNotSafe() {
        List<Integer> list = new ArrayList();

        // 采用匿名内部类实现多线程
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    list.add(i);
                }
            }
        });
        t1.start();

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    list.add(i);
                }
            }
        });
        t2.start();

        for (int i = 0; i < 100; i++) {
            list.add(i);
        }

        System.out.println(list.toString());
    }
}
